package com.ruoyi.web.controller.project.excel;

import lombok.Data;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

@Data
public class ZlSheet {
    /**
     * 工作簿
     */
    private XSSFWorkbook wb;

    private XSSFSheet sheet;

    /**
     * 当前行
     */
    private int rowIndex = 0;

    /**
     * 当前列
     */
    private int cellIndex = 0;

    /**
     * 当前操作的row
     */
    private ZlRow nowRow;

    /**
     * 当前操作的cell
     */
    private ZlCell nowCell;


    private XSSFDrawing patriarch;

    /**
     * 所有行
     */
    private LinkedList<ZlRow> rows = new LinkedList<>();


    public ZlSheet(XSSFWorkbook wb){
        this(wb,"sheet");
    }

    public ZlSheet(XSSFWorkbook wb,String sheetName){
        this.wb = wb;
        this.sheet = this.wb.createSheet(sheetName);
        //隐藏网格线  是否显示网格线  true显示，false 不显示
        this.sheet.setDisplayGridlines(false);
        this.patriarch = sheet.createDrawingPatriarch();
    }


    public List<ZlRow> getRows() {
        return rows;
    }

    /**
     * 创建下一个cell
     */
    public ZlSheet createNextCell(Object content){
        if(this.nowRow == null){
            nextRow();
        }
        ZlCell cell = new ZlCell(this.wb,this,this.nowRow,this.cellIndex,content);
        this.cellIndex = this.cellIndex + 1;
        this.nowCell = cell;
        this.nowRow.getCells().addLast(cell);
        return this;
    }

    /**
     * 创建下一个cell
     */
    public ZlSheet createNextCell(Object content,boolean hold){
        ZlCell cell = new ZlCell(this.wb,this,this.nowRow,this.cellIndex,content,hold);
        this.cellIndex = this.cellIndex + 1;
        this.nowCell = cell;
        this.nowRow.getCells().addLast(cell);
        return this;
    }

    /**
     * 创建下一个cell
     */
    public ZlSheet createNextCell(Object content,boolean hold,int width){
        ZlCell cell = new ZlCell(this.wb,this,this.nowRow,this.cellIndex,content,hold,width);
        this.cellIndex = this.cellIndex + 1;
        this.nowCell = cell;
        this.nowRow.getCells().addLast(cell);
        return this;
    }

    /**
     * 创建下一个cell
     */
    public ZlSheet createNextCell(Object content,boolean hold,int width,short fontSize){
        ZlCell cell = new ZlCell(this.wb,this,this.nowRow,this.cellIndex,content,hold,width,fontSize);
        this.cellIndex = this.cellIndex + 1;
        this.nowCell = cell;
        this.nowRow.getCells().addLast(cell);
        return this;
    }


    /**
     * 创建下一个图片cell
     */
    public ZlSheet createNextImageCell(int width,String url){
        ZlCell cell = new ZlCell(this.wb,this,this.nowRow,this.cellIndex,width,url);
        this.cellIndex = this.cellIndex + 1;
        this.nowCell = cell;
        this.nowRow.getCells().addLast(cell);
        return this;
    }

    /**
     * 创建下一个cell 用多个单元格合并
     * @param indexNumber  下一个单元格的结束索引
     * @param content   单元格内容
     * @param hold   是否粗体
     */
    public ZlSheet createCell(Integer indexNumber,Object content,boolean hold){
        this.createCell(indexNumber,content,hold,0,(short)13);
        return this;
    }

    /**
     * 创建下一个cell 用多个单元格合并
     * @param indexNumber  下一个单元格的结束索引
     * @param content   单元格内容
     * @param hold   是否粗体
     * @param fontSize  字体大小
     */
    public ZlSheet createCell(Integer indexNumber,Object content,boolean hold,short fontSize){
        this.createCell(indexNumber,content,hold,0,fontSize);
        return this;
    }

    /**
     * 创建下一个cell 用多个单元格合并
     * @param indexNumber  下一个单元格的结束索引
     * @param content   单元格内容
     * @param width   单元格宽度
     * @param hold   是否粗体
     */
    public ZlSheet createCell(Integer indexNumber,Object content,int width,boolean hold){
        this.createCell(indexNumber,content,hold,width,(short)13);
        return this;
    }

    /**
     * 创建一个大的cell单元格，合并多个横向单元格
     */
    public ZlSheet createCell(Integer indexNumber,Object content,boolean hold,int width,short fontSize){
        ZlCell firstCell = null;
        ZlCell lastCell = null;
        for(int i = this.cellIndex ; i < indexNumber ; i ++){
            ZlCell cell = new ZlCell(this.wb,this,this.nowRow,i,content,hold,width,fontSize);
            if(firstCell == null) {
                firstCell = cell;
            }
            if(i == indexNumber - 1){
                lastCell = cell;
            }
            this.nowRow.getCells().addLast(cell);
        }
        if(firstCell != null && lastCell != null) {
            firstCell.mergeCell(this.nowRow.getRowNo(), lastCell.getCellNo());
        }
        this.nowCell = lastCell;
        this.cellIndex = indexNumber;
        return this;
    }

    /**
     * 供 newCell使用的方法
     */
    public ZlSheet createNextCell(ZlCell cell){
        this.cellIndex = this.cellIndex + 1;
        this.nowCell = cell;
        this.nowRow.getCells().addLast(cell);
        return this;
    }

    /**
     * 创建一个可以自定义cell各种风格
     */
    public ZlCell newCell(Object content,boolean hold,int width,short fontSize){
        return new ZlCell(this.wb,this,this.nowRow,this.cellIndex,content,hold,width,fontSize);
    }

    public ZlCell newMergeCell(Integer indexNumber,Object content,boolean hold){
        return newMergeCell(indexNumber,content,hold,0,(short)13);
    }

    public ZlCell newMergeCell(Integer indexNumber,Object content,boolean hold,short fontSize){
        return newMergeCell(indexNumber,content,hold,0,fontSize);
    }

    /**
     * 创建一个大的cell单元格，合并多个横向单元格 newCell使用的方法
     */
    public ZlCell newMergeCell(Integer indexNumber,Object content,boolean hold,int width,short fontSize){
        ZlCell firstCell = null;
        ZlCell lastCell = null;
        for(int i = this.cellIndex ; i < indexNumber ; i ++){
            ZlCell cell = new ZlCell(this.wb,this,this.nowRow,i,content,hold,width,fontSize);
            if(firstCell == null) {
                firstCell = cell;
            }
            if(i == indexNumber - 1){
                lastCell = cell;
            }
            this.nowRow.getCells().addLast(cell);
        }
        if(firstCell != null && lastCell != null) {
            firstCell.mergeCell(this.nowRow.getRowNo(), lastCell.getCellNo());
        }
        this.nowCell = lastCell;
        this.cellIndex = indexNumber;
        return firstCell;
    }

    /**
     * 供 newCell使用的方法
     */
    public ZlSheet createCell(ZlCell cell){
        this.nowCell = cell;
        this.nowRow.getCells().addLast(cell);
        return this;
    }


    /**
     * 合并单元格
     */
    public ZlSheet mergeCell(Integer firstRowIndex,Integer firstCellIndex,Integer endRowIndex,Integer endCellIndex){
        ZlCell topCell  = this.rows.get(firstRowIndex).getCells().get(firstCellIndex);
        topCell.setContent(this.nowCell.getContent());
        topCell.mergeCell(endRowIndex,endCellIndex);
        return this;
    }

    /**
     * 向上方合并单元格
     *
     * 这个方法需要在需要合并的单元格下一行(或多行)需要合并的列创建后调用
     */
    public ZlSheet mergeTop(Integer topIndex){
        LinkedList<ZlCell> cells = this.rows.get(this.rowIndex - 1 - topIndex).getCells();
        ZlCell topCell  = getTopCell(cells);
        topCell.setContent(this.nowCell.getContent());
        topCell.mergeCell(this.nowRow.getRowIndex(),this.nowCell.getCellIndex());
        return this;
    }

    /**
     * 向上方合并单元格
     *
     * 这个方法需要在需要合并的单元格下一行(或多行)需要合并的列创建后调用
     */
    public ZlSheet mergeTop(Integer topIndex,Object content){
        LinkedList<ZlCell> cells = this.rows.get(this.rowIndex - 1 - topIndex).getCells();
        ZlCell topCell  = getTopCell(cells);
        topCell.setContent(content);
        topCell.mergeCell(this.nowRow.getRowIndex(),this.nowCell.getCellIndex());
        return this;
    }

    private ZlCell getTopCell(LinkedList<ZlCell> cells){
        int i = cellIndex - 1;
        ZlCell zlCell = cells.get(i);
        String cellNo = zlCell.getCellNo();
        if(ObjectUtils.isEmpty(cellNo)){
            return zlCell;
        }

        while(i>=1){
            ZlCell beforeCell = cells.get(i - 1);
            if (beforeCell.getCellNo().equals(cellNo)) {
                zlCell = beforeCell;
                i--;
            }else{
                break;
            }
        }
        return zlCell;
    }


    /**
     * 下一行
     */
    public ZlSheet nextRow(){
        this.nextRow(23);
        return this;
    }

    /**
     * 下一行
     */
    public ZlSheet nextRow(int height){
        ZlRow row = new ZlRow(this,this.rowIndex,height);
        this.rows.addLast(row);
        this.nowRow = row;
        this.cellIndex = 0;
        this.rowIndex = this.rowIndex + 1;
        return this;
    }


    /**
     * 写入文件
     */
    public void writeFile(String path){
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        try {
            this.wb.write(stream);
            File file = new File(path);
            if(!file.exists()){
                file.createNewFile();
            }
            FileOutputStream outputStream = new FileOutputStream(file);
            stream.writeTo(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
